package cc.rengu.igas.acct.common.dao.impl;

import cc.rengu.igas.acct.common.constant.AcctCommonConstant;
import cc.rengu.igas.acct.common.constant.AcctSqlMapperId;
import cc.rengu.igas.acct.common.dao.AcctSequenceMapper;
import cc.rengu.igas.acct.common.dao.MapperCommon;
import cc.rengu.igas.acct.common.entity.AcctDetail;
import cc.rengu.igas.acct.common.enums.AcctRespCodeEnum;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.entity.SequenceInfo;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.DbsUtil;
import cc.rengu.oltp.utility.util.RandomUtil;
import cc.rengu.utility.base.StringUtil;
import cc.rengu.utility.cache.UnifiedCache;
import cc.rengu.utility.dbs.Database;

import static cc.rengu.igas.acct.common.constant.AcctCommonConstant.DATETIME_FORMAT_14;

/**
 * 账户数据库Sequence操作实现类
 *
 * @author lizhangtao
 * @version 1.0
 * @date 2020/4/9
 */
public class AcctSequenceMapperImpl extends MapperCommon implements AcctSequenceMapper {

    /**
     * 获取交易流水号Sequence
     *
     * @return Sequence字符串
     * @throws Exception 顶层异常
     */
    @Override
    public String getNextAcctNoSequenceNo() throws BizException {
        try {
            extractDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            return getNextAcctNoSequenceNo(dbsUtil);
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 获取交易流水号Sequence
     *
     * @param dbsUtil 数据库操作句柄
     * @return Sequence字符串
     * @throws Exception 顶层异常
     */
    @Override
    public String getNextAcctNoSequenceNo(DbsUtil dbsUtil) throws BizException {
        try {
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE, AcctSqlMapperId.GET_ACCT_NO_SEQ);
            SequenceInfo sequenceInfo = new SequenceInfo();
            int iReturnCode = dbsUtil.dbsExecuteSql(sqlStr, null, sequenceInfo);
            if (Database.DBS_SUCCESS != iReturnCode) {
                rglog.error("获取账号SEQUENCE序号失败,iReturnCode:<{}>", iReturnCode);
                throw new BizException(AcctRespCodeEnum.DB_ERROR.getRespCode(), AcctRespCodeEnum.DB_ERROR.getRespDesc());
            }
            String acctSeqNo = sequenceInfo.getSequenceNo();
            /* 不足长度前补0 */
            int len = 3;
            if (acctSeqNo.length() < len) {
                String format = "%0" + (len - acctSeqNo.length()) + "d";
                return String.format(format, 0) + acctSeqNo;
            } else if (acctSeqNo.length() == len) {
                return acctSeqNo;
            } else {
                rglog.error("账户序列长度超长");
                throw new BizException(AcctRespCodeEnum.DB_ERROR.getRespCode(), AcctRespCodeEnum.DB_ERROR.getRespDesc());
            }
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }

    /**
     * 获取交易流水号Sequence， 不带事物操作
     * 流水号=账户类型2位 + 14位系统时间 + 10位序列号 + 6位随机数
     *
     * @param acctDetail 账户记账明细实体，需要创建日期时间yyyy-MM-dd HH:mm:ss.SSS，账户类型
     * @param dbsUtil    数据库操作句柄
     * @return Sequence字符串
     * @throws Exception 顶层异常
     */
    @Override
    public String getNextAcctSeqNumSequenceNo(AcctDetail acctDetail, DbsUtil dbsUtil) throws BizException {
        try {
            String sqlStr = (String) UnifiedCache.get(AppParamConstant.SQL_MAPPER_CACHE, AcctSqlMapperId.GET_ACCT_SEQ_NUM_SEQ);
            String dateTime14 = DateUtil.dateStringFormatConvert(acctDetail.getCreateTime(), AcctCommonConstant.DATETIME_FORMAT_MS, DATETIME_FORMAT_14);
            SequenceInfo sequenceInfo = new SequenceInfo();
            int iReturnCode = dbsUtil.dbsExecuteTransactionSql(sqlStr, null, sequenceInfo);
            if (Database.DBS_SUCCESS != iReturnCode) {
                rglog.error("获取交易流水SEQUENCE序号失败,iReturnCode:<{}>", iReturnCode);
                return null;
            }
            String acctSeqNo = sequenceInfo.getSequenceNo();
            /* 不足长度前补0 */
            int len = 10;
            if (acctSeqNo.length() < len) {
                String format = "%0" + (len - acctSeqNo.length()) + "d";
                return acctDetail.getAcctType() + dateTime14 + String.format(format, 0) + acctSeqNo + RandomUtil.randomNumStr(6);
            } else if (acctSeqNo.length() == len) {
                return acctDetail.getAcctType() + dateTime14 + acctSeqNo + RandomUtil.randomNumStr(6);
            } else {
                rglog.error("流水号序列长度超长");
                throw new BizException(AcctRespCodeEnum.DB_ERROR.getRespCode(), AcctRespCodeEnum.DB_ERROR.getRespDesc());
            }
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            throw new BizException(AcctRespCodeEnum.DB_EXCEPTION.getRespCode(), AcctRespCodeEnum.DB_EXCEPTION.getRespDesc());
        }
    }
}
